Correct problems with earlier fix for bug #480065
authorKristian Rietveld <kris@gtk.org>
Mon, 21 Dec 2009 21:33:59 +0000 (22:33 +0100)
committerTristan Van Berkom <tristan.van.berkom@gmail.com>
Sun, 4 Apr 2010 00:53:38 +0000 (20:53 -0400)
Initialize event_last_[xy] to out of range coordinates and also update
these values in enter and leave notify.  Fix up calls to
update_prelight() from size allocate.  Unconditionally doing these calls
caused problems with hover selection.  Now we only do this call when
the "width before the expander column" has changed.  (Which might be
awkward, but it is the best heuristic I could come up with so far).

gtk/gtktreeprivate.h
gtk/gtktreeview.c

index 43c6e31069a26573b50e42b3878a6c60a9a96209..8a84e89cdb75988aba1196c900c6b143d3f2dbb7 100644 (file)
@@ -177,6 +177,8 @@ struct _GtkTreeViewPrivate
   GList *column_drag_info;
   GtkTreeViewColumnReorder *cur_reorder;
 
+  gint prev_width_before_expander;
+
   /* Interactive Header reordering */
   GdkWindow *drag_window;
   GdkWindow *drag_highlight_window;
index ef4cb4674278e9f6afbb555a2af9bf26fdc923f8..4be8f9e74242511de23296e4d9a0d6e9140cb148 100644 (file)
@@ -1382,6 +1382,9 @@ gtk_tree_view_init (GtkTreeView *tree_view)
 
   tree_view->priv->last_button_x = -1;
   tree_view->priv->last_button_y = -1;
+
+  tree_view->priv->event_last_x = -10000;
+  tree_view->priv->event_last_y = -10000;
 }
 
 \f
@@ -2056,6 +2059,25 @@ gtk_tree_view_size_request (GtkWidget      *widget,
     }
 }
 
+static int
+gtk_tree_view_calculate_width_before_expander (GtkTreeView *tree_view)
+{
+  int width = 0;
+  GList *list;
+  gboolean rtl;
+
+  rtl = (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_RTL);
+  for (list = (rtl ? g_list_last (tree_view->priv->columns) : g_list_first (tree_view->priv->columns));
+       list->data != tree_view->priv->expander_column;
+       list = (rtl ? list->prev : list->next))
+    {
+      GtkTreeViewColumn *column = list->data;
+
+      width += column->width;
+    }
+
+  return width;
+}
 
 static void
 invalidate_column (GtkTreeView       *tree_view,
@@ -2473,14 +2495,30 @@ gtk_tree_view_size_allocate (GtkWidget     *widget,
            }
        }
 
+      if (width_changed && tree_view->priv->expander_column)
+        {
+          /* Might seem awkward, but is the best heuristic I could come up
+           * with.  Only if the width of the columns before the expander
+           * changes, we will update the prelight status.  It is this
+           * width that makes the expander move vertically.  Always updating
+           * prelight status causes trouble with hover selections.
+           */
+          gint width_before_expander;
+
+          width_before_expander = gtk_tree_view_calculate_width_before_expander (tree_view);
+
+          if (tree_view->priv->prev_width_before_expander
+              != width_before_expander)
+              update_prelight (tree_view,
+                               -tree_view->priv->event_last_x,
+                               -tree_view->priv->event_last_y);
+
+          tree_view->priv->prev_width_before_expander = width_before_expander;
+        }
+
       /* This little hack only works if we have an LTR locale, and no column has the  */
       if (width_changed)
        {
-          if (tree_view->priv->tree)
-            update_prelight (tree_view,
-                             tree_view->priv->event_last_x,
-                             tree_view->priv->event_last_y);
-
          if (gtk_widget_get_direction (GTK_WIDGET (tree_view)) == GTK_TEXT_DIR_LTR &&
              ! has_expand_column)
            invalidate_last_column (tree_view);
@@ -3299,6 +3337,16 @@ prelight_or_select (GtkTreeView *tree_view,
     do_prelight (tree_view, tree, node, x, y);
 }
 
+static void
+ensure_unprelighted (GtkTreeView *tree_view)
+{
+  do_prelight (tree_view,
+              NULL, NULL,
+              -1000, -1000); /* coords not possibly over an arrow */
+
+  g_assert (tree_view->priv->prelight_node == NULL);
+}
+
 static void
 update_prelight (GtkTreeView *tree_view,
                  gint         x,
@@ -3308,6 +3356,12 @@ update_prelight (GtkTreeView *tree_view,
   GtkRBTree *tree;
   GtkRBNode *node;
 
+  if (x == -10000)
+    {
+      ensure_unprelighted (tree_view);
+      return;
+    }
+
   new_y = TREE_WINDOW_Y_TO_RBTREE_Y (tree_view, y);
   if (new_y < 0)
     new_y = 0;
@@ -3319,16 +3373,6 @@ update_prelight (GtkTreeView *tree_view,
     prelight_or_select (tree_view, tree, node, x, y);
 }
 
-static void
-ensure_unprelighted (GtkTreeView *tree_view)
-{
-  do_prelight (tree_view,
-              NULL, NULL,
-              -1000, -1000); /* coords not possibly over an arrow */
-
-  g_assert (tree_view->priv->prelight_node == NULL);
-}
-
 
 
 
@@ -5542,6 +5586,9 @@ gtk_tree_view_enter_notify (GtkWidget        *widget,
     new_y = 0;
   _gtk_rbtree_find_offset (tree_view->priv->tree, new_y, &tree, &node);
 
+  tree_view->priv->event_last_x = event->x;
+  tree_view->priv->event_last_y = event->y;
+
   if ((tree_view->priv->button_pressed_node == NULL) ||
       (tree_view->priv->button_pressed_node == node))
     prelight_or_select (tree_view, tree, node, event->x, event->y);
@@ -5566,6 +5613,9 @@ gtk_tree_view_leave_notify (GtkWidget        *widget,
                                    tree_view->priv->prelight_node,
                                    NULL);
 
+  tree_view->priv->event_last_x = -10000;
+  tree_view->priv->event_last_y = -10000;
+
   prelight_or_select (tree_view,
                      NULL, NULL,
                      -1000, -1000); /* coords not possibly over an arrow */